package com.aptana.js.internal.core.parsing.sdoc;

import com.aptana.js.internal.core.parsing.sdoc.model.*;
import java.util.ArrayList;
import java.util.List;
import beaver.*;

/**
 * This class is a LALR parser generated by
 * <a href="http://beaver.sourceforge.net">Beaver</a> v0.9.6.1
 * from the grammar specification "SDoc.grammar".
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class SDocParser extends Parser {
	static public class AltGoals {
		static public final short Types = 43;
	}

	static final ParsingTables PARSING_TABLES = new ParsingTables(
		"U9pjLsjGL6KOVixPNLP44HKZKr145abSbeKbi4pDQvgNrD9Kj2mJAoerqxIIobkPvQ#QQQR" +
		"yrzIlfcbgHWgxQ9bbPQPPLfgLaeM5MPPbV3tVTzuz7BQbQFhdkCppFizx#TxlSiwUim3sGW" +
		"p3fHY2It0nXcCmXk8os2XMMvH2RsIZ5yPY6gx13RWPAx0AQr6EaHYDoPY2ERWMyx0Gox4Q6" +
		"n1Dqabto4V0S66xExMthgpTbOycMTkvoDaN2I827ws#tyAg6Id8H3ewYkt9J5zqa7mFX93Q" +
		"Af$7J1yKqOv01Ur5I6kLTsmyUoKAQ3jXUj8QFKCEEiFFwXBwJdmZrIF8SFqWkYICyyun0JF" +
		"4hnIUY4diCHkb9jyDLOQxOYvkDJCwewupt1tNcrYM6QKZYr6DHKRTWziDtu#x39#7U$6WgG" +
		"xXVBTJ20#uUWaUCXp0mrZ6dUNW0Wmmt1#3c1b5Z44kpsG4hY2cCbE0gsdxOHRzcwYMeiQCk" +
		"1ltCRA6Ae3rn8KOY83wKvr1JFtElUg$op4Eur6fNb4lgphwLx5k9Z4VDs81$LkeRyCTk1Ch" +
		"gMg9IgoZZQa$OF49vkF91tZzWxpUgRoI5So3roET9zwL9zUT9zg3#yxYVdjoBxtaYlNX7PB" +
		"BDUTnN$b9EZaTIlvZf$RF#7$MTYvoDaRqjyEI#mq8yocGngUEOpEOwS9g9wz7#V#Mpp2sYD" +
		"zI2yNyJdhpZct9XcZ3N4Eo6Zr3cD$vY5GxyIXL6MUrtBf0mhZ4EHo$o5CLvOnb9XzcNdC1s" +
		"JOpnaTf7a3MiL8pIaS2Z0IDigKcpdwtGmgxnZkbI0UjWr9PGYvaJPWxYxYiCngbF9Eu3bF7" +
		"Ano$C654cDqYHAbH#XCbYioV3p6kg8Ym3VjOuI3c#kLSjz$DEB6ewREfrf0rXAOJUGrHGwo" +
		"N#19YXUW5n0PYhVXrn8kY7oUsYrv6D8kUB$o4jhK9OBmQi2toKl6VfCbjNSDd4kmWSykbvb" +
		"cYoj7sI9h#YX$gKTGLv34oRh7moiHv$mdyh2Os4eyHczblBEVRHHvF$ndYUUe9n4HY4lqw6" +
		"RUDq7MJMSyQwodw#sITK#Y$HEodSr3g6uIRX4zBxJJMDP2dastPSngHoTWCyXRYCD54PBUi" +
		"s#RrisUAdkKvuv34ggZhYT#8OedDfNwJE4DKIFrmOXnpyyWxoJPvgkHcUyv9dq6rrZp#FP9" +
		"VvQIiOSdFrbhKHlmvZwxtw0F2ZSJH9EEE4oVr6iNdcTYTMzVOVBxPwKIcr9oWxkRfmUjjFI" +
		"srcPxu78drJhRcji1nfpWcspbdEqTwP4cEvsptIwYl4MvcBkJHUUJDddtmUsBdny#A$8Amt" +
		"7$MLazjdiHsY9z2X3rw856Wx#jsx6Utfsyg4M5ihoVMaU3Jn3ealZxl2e#ECNT4UXtpZ8iv" +
		"Z4tmVDJ7QW$jX#BjLk$HVc3qBlKkxVl4EyRVgVQgZzG#ghU97IRsbdf3lKxcFQsscyYsLjr" +
		"$K8tgE$MzEgr#LQVKB#fdTLBzf4we9lMZulLInuXltUe6uKPrbFQ8wttZgg#9huZ3n9Tkz1" +
		"3jGRTBe$f2lMRKgqIzsih8vsxkCrSTeFtKzJuXzglZqcGqVsTQXCtVd1QVSZw1txoR1fdtu" +
		"B#ZpBmHzNiFX6NUa2q89EX06$cK93KEw$#I8knR8WWR#0Y$i4zYVaykuE6WvFJRjGFVTvP1" +
		"kO7FvHWvZi5$0GM5zcW=");

	// suppress parser error reporting and let the custom error recovery mechanism handle it
	private static class SDocEvents extends Events
	{
		public void scannerError(Scanner.Exception e)
		{
		}

		public void syntaxError(Symbol token)
		{
		}

		public void unexpectedTokenRemoved(Symbol token)
		{
		}

		public void missingTokenInserted(Symbol token)
		{
		}

		public void misspelledTokenReplaced(Symbol token)
		{
		}

		public void errorPhraseRemoved(Symbol error)
		{
		}
	}

	/**
	 * parse
	 *
	 * @param source
	 */
	public Object parse(String source) throws java.lang.Exception
	{
		return parse(source, 0);
	}

	/**
	 * parse
	 *
	 * @param source
	 * @param offset
	 */
	public Object parse(String source, int offset) throws java.lang.Exception
	{
		// SDocScanner fScanner = new SDocScanner();
		SDocFlexScanner fScanner = new SDocFlexScanner();

		fScanner.setOffset(offset);
		fScanner.setSource(source);

		return parse(fScanner);
	}

	/**
	 * parseType
	 * 
	 * @param source
	 * @return
	 * @throws java.lang.Exception
	 */
	public List<Type> parseType(String source) throws java.lang.Exception
	{
		// SDocScanner fScanner = new SDocScanner();
		SDocFlexScanner fScanner = new SDocFlexScanner();

		fScanner.setOffset(0);
		fScanner.setSource(source);
		// fScanner.queueTypeTokens(0, source.length());

		// NOTE: we need to clear the scanner source since queueTypeTokens doesn't set the offset of one of the inner
		// scanners resulting in double scanning
		// fScanner.setSource(StringUtil.EMPTY);

		fScanner.yybegin(SDocFlexScanner.TYPES);

		Object result = parse(fScanner, AltGoals.Types);

		return (result instanceof List) ? (List<Type>) result : null;
	}

	public SDocParser() {
		super(PARSING_TABLES);


	report = new SDocEvents();
	}

	protected Symbol invokeReduceAction(int rule_num, int offset) {
		switch(rule_num) {
			case 3: // Block = START_DOCUMENTATION Text.text END_DOCUMENTATION
			{
					final Symbol text = _symbols[offset + 2];
					
			return new DocumentationBlock((String) text.value);
			}
			case 4: // Block = START_DOCUMENTATION Tags.tags END_DOCUMENTATION
			{
					final Symbol tags = _symbols[offset + 2];
					
			return new DocumentationBlock((List<Tag>) tags.value);
			}
			case 5: // Block = START_DOCUMENTATION Text.text Tags.tags END_DOCUMENTATION
			{
					final Symbol text = _symbols[offset + 2];
					final Symbol tags = _symbols[offset + 3];
					
			return new DocumentationBlock((String) text.value, (List<Tag>) tags.value);
			}
			case 6: // Text = Text.text TextPart.part
			{
					final Symbol text = _symbols[offset + 1];
					final Symbol part = _symbols[offset + 2];
					
			return new Symbol(text.value + " " + part.value);
			}
			case 17: // Tags = Tags.tags Tag.tag
			{
					final Symbol tags = _symbols[offset + 1];
					final Symbol _symbol_tag = _symbols[offset + 2];
					final Tag tag = (Tag) _symbol_tag.value;
					
			((List<Tag>) tags.value).add(tag);

			return tags;
			}
			case 18: // Tags = Tag.tag
			{
					final Symbol _symbol_tag = _symbols[offset + 1];
					final Tag tag = (Tag) _symbol_tag.value;
					
			List<Tag> tags = new ArrayList<Tag>();

			tags.add(tag);

			return new Symbol(tags);
			}
			case 21: // Tag = ADVANCED opt$Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new AdvancedTag((String) text.value);
			}
			case 22: // Tag = ALIAS Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new AliasTag((String) text.value);
			}
			case 23: // Tag = AUTHOR Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new AuthorTag((String) text.value);
			}
			case 24: // Tag = CLASS_DESCRIPTION LCURLY Namespace.name RCURLY Text.text
			{
					final Symbol _symbol_name = _symbols[offset + 3];
					final String name = (String) _symbol_name.value;
					final Symbol text = _symbols[offset + 5];
					
			return new ClassDescriptionTag(name, (String) text.value);
			}
			case 25: // Tag = CONSTRUCTOR opt$Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new ConstructorTag((String) text.value);
			}
			case 26: // Tag = EXAMPLE Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new ExampleTag((String) text.value);
			}
			case 27: // Tag = EXCEPTION LCURLY Types.types RCURLY opt$Text.text
			{
					final Symbol types = _symbols[offset + 3];
					final Symbol text = _symbols[offset + 5];
					
			return new ExceptionTag((List<Type>) types.value, (String) text.value);
			}
			case 28: // Tag = EXTENDS LCURLY Types.types RCURLY opt$Text.text
			{
					final Symbol types = _symbols[offset + 3];
					final Symbol text = _symbols[offset + 5];
					
			return new ExtendsTag((List<Type>) types.value, (String) text.value);
			}
			case 29: // Tag = INTERNAL opt$Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new InternalTag((String) text.value);
			}
			case 30: // Tag = METHOD opt$Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new MethodTag((String) text.value);
			}
			case 31: // Tag = MODULE opt$Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new ModuleTag((String) text.value);
			}
			case 32: // Tag = NAMESPACE LCURLY Namespace.name RCURLY opt$Text.text
			{
					final Symbol _symbol_name = _symbols[offset + 3];
					final String name = (String) _symbol_name.value;
					final Symbol text = _symbols[offset + 5];
					
			return new NamespaceTag(name, (String) text.value);
			}
			case 33: // Tag = OVERVIEW Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new OverviewTag((String) text.value);
			}
			case 34: // Tag = PARAM LCURLY Types.types RCURLY ParamName.name opt$Text.text
			{
					final Symbol types = _symbols[offset + 3];
					final Symbol _symbol_name = _symbols[offset + 5];
					final Parameter name = (Parameter) _symbol_name.value;
					final Symbol text = _symbols[offset + 6];
					
			return new ParamTag(name, (List<Type>) types.value, (String) text.value);
			}
			case 35: // Tag = PRIVATE opt$Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new PrivateTag((String) text.value);
			}
			case 36: // Tag = PROPERTY LCURLY Types.types RCURLY opt$Text.text
			{
					final Symbol types = _symbols[offset + 3];
					final Symbol text = _symbols[offset + 5];
					
			return new PropertyTag((List<Type>) types.value, (String) text.value);
			}
			case 37: // Tag = RETURN LCURLY Types.types RCURLY opt$Text.text
			{
					final Symbol types = _symbols[offset + 3];
					final Symbol text = _symbols[offset + 5];
					
			return new ReturnTag((List<Type>) types.value, (String) text.value);
			}
			case 38: // Tag = SEE Text.text
			{
					final Symbol text = _symbols[offset + 2];
					
			return new SeeTag((String) text.value);
			}
			case 39: // Tag = TYPE LCURLY Types.types RCURLY opt$Text.text
			{
					final Symbol types = _symbols[offset + 3];
					final Symbol text = _symbols[offset + 5];
					
			return new TypeTag((List<Type>) types.value, (String) text.value);
			}
			case 40: // Tag = UNKNOWN.name opt$Text.text
			{
					final Symbol _symbol_name = _symbols[offset + 1];
					final String name = (String) _symbol_name.value;
					final Symbol text = _symbols[offset + 2];
					
			return new UnknownTag(name, (String) text.value);
			}
			case 41: // Types = Types.types TypeDelimiter Type.type
			{
					final Symbol types = _symbols[offset + 1];
					final Symbol _symbol_type = _symbols[offset + 3];
					final Type type = (Type) _symbol_type.value;
					
			((List<Type>) types.value).add(type);

			return types;
			}
			case 42: // Types = Type.type
			{
					final Symbol _symbol_type = _symbols[offset + 1];
					final Type type = (Type) _symbol_type.value;
					
			List<Type> types = new ArrayList<Type>();

			types.add(type);

			return new Symbol(types);
			}
			case 45: // Type = IDENTIFIER.name
			{
					final Symbol _symbol_name = _symbols[offset + 1];
					final String name = (String) _symbol_name.value;
					
			return new Type(name);
			}
			case 46: // Type = IDENTIFIER.name LBRACKET RBRACKET
			{
					final Symbol _symbol_name = _symbols[offset + 1];
					final String name = (String) _symbol_name.value;
					
			return new ArrayType(new Type(name));
			}
			case 47: // Type = CLASS LESS_THAN Type.memberType GREATER_THAN
			{
					final Symbol _symbol_memberType = _symbols[offset + 3];
					final Type memberType = (Type) _symbol_memberType.value;
					
			return new ClassType(memberType);
			}
			case 48: // Type = ARRAY LBRACKET RBRACKET
			{
					
			return new ArrayType();
			}
			case 49: // Type = FUNCTION LBRACKET RBRACKET
			{
					
			return new FunctionType();
			}
			case 50: // Type = ARRAY
			{
					
			return new ArrayType();
			}
			case 51: // Type = ARRAY LESS_THAN Type.memberType GREATER_THAN
			{
					final Symbol _symbol_memberType = _symbols[offset + 3];
					final Type memberType = (Type) _symbol_memberType.value;
					
			return new ArrayType(memberType);
			}
			case 52: // Type = FUNCTION
			{
					
			return new FunctionType();
			}
			case 53: // Type = FUNCTION ReturnDelimiter Type.returnType
			{
					final Symbol _symbol_returnType = _symbols[offset + 3];
					final Type returnType = (Type) _symbol_returnType.value;
					
			FunctionType function = new FunctionType();

			function.addReturnType(returnType);

			return function;
			}
			case 54: // Type = FUNCTION ReturnDelimiter LPAREN Types.returnTypes RPAREN
			{
					final Symbol returnTypes = _symbols[offset + 4];
					
			FunctionType function = new FunctionType();

			for (Type returnType : (List<Type>) returnTypes.value)
			{
				function.addReturnType(returnType);
			}

			return function;
			}
			case 55: // Type = FUNCTION LPAREN RPAREN
			{
					
			return new FunctionType();
			}
			case 56: // Type = FUNCTION LPAREN RPAREN ReturnDelimiter Type.returnType
			{
					final Symbol _symbol_returnType = _symbols[offset + 5];
					final Type returnType = (Type) _symbol_returnType.value;
					
			FunctionType function = new FunctionType();

			function.addReturnType(returnType);

			return function;
			}
			case 57: // Type = FUNCTION LPAREN RPAREN ReturnDelimiter LPAREN Types.returnTypes RPAREN
			{
					final Symbol returnTypes = _symbols[offset + 6];
					
			FunctionType function = new FunctionType();

			for (Type returnType : (List<Type>) returnTypes.value)
			{
				function.addReturnType(returnType);
			}

			return function;
			}
			case 58: // Type = FUNCTION LPAREN Types.parameterTypes RPAREN
			{
					final Symbol parameterTypes = _symbols[offset + 3];
					
			FunctionType function = new FunctionType();

			for (Type parameterType : (List<Type>) parameterTypes.value)
			{
				function.addParameterType(parameterType);
			}

			return function;
			}
			case 59: // Type = FUNCTION LPAREN Types.parameterTypes RPAREN ReturnDelimiter Type.returnType
			{
					final Symbol parameterTypes = _symbols[offset + 3];
					final Symbol _symbol_returnType = _symbols[offset + 6];
					final Type returnType = (Type) _symbol_returnType.value;
					
			FunctionType function = new FunctionType();

			for (Type parameterType : (List<Type>) parameterTypes.value)
			{
				function.addParameterType(parameterType);
			}

			function.addReturnType(returnType);

			return function;
			}
			case 60: // Type = FUNCTION LPAREN Types.parameterTypes RPAREN ReturnDelimiter LPAREN Types.returnTypes RPAREN
			{
					final Symbol parameterTypes = _symbols[offset + 3];
					final Symbol returnTypes = _symbols[offset + 7];
					
			FunctionType function = new FunctionType();

			for (Type parameterType : (List<Type>) parameterTypes.value)
			{
				function.addParameterType(parameterType);
			}

			for (Type returnType : (List<Type>) returnTypes.value)
			{
				function.addReturnType(returnType);
			}

			return function;
			}
			case 63: // ParamName = TEXT.name
			{
					final Symbol _symbol_name = _symbols[offset + 1];
					final String name = (String) _symbol_name.value;
					
			return new Parameter(name);
			}
			case 64: // ParamName = LBRACKET TEXT.name RBRACKET
			{
					final Symbol _symbol_name = _symbols[offset + 2];
					final String name = (String) _symbol_name.value;
					
			Parameter result = new Parameter(name);

			result.setUsage(Usage.OPTIONAL);

			return result;
			}
			case 65: // ParamName = ELLIPSIS
			{
					
			Parameter result = new Parameter("...");

			result.setUsage(Usage.ONE_OR_MORE);

			return result;
			}
			case 66: // ParamName = LBRACKET ELLIPSIS RBRACKET
			{
					
			Parameter result = new Parameter("...");

			result.setUsage(Usage.ZERO_OR_MORE);

			return result;
			}
			case 19: // opt$Text = 
			{
				return new Symbol(null);
			}
			case 0: // $goal = Grammar
			case 2: // Grammar = Block
			case 7: // Text = TextPart
			case 8: // TextPart = TEXT
			case 9: // TextPart = LBRACKET
			case 10: // TextPart = RBRACKET
			case 11: // TextPart = LCURLY
			case 12: // TextPart = RCURLY
			case 13: // TextPart = POUND
			case 14: // TextPart = IDENTIFIER
			case 15: // TextPart = COLON
			case 16: // TextPart = ERROR
			case 20: // opt$Text = Text
			case 43: // TypeDelimiter = COMMA
			case 44: // TypeDelimiter = PIPE
			case 61: // ReturnDelimiter = COLON
			case 62: // ReturnDelimiter = ARROW
			case 67: // Namespace = IDENTIFIER
			case 68: // Namespace = FUNCTION
			case 69: // Namespace = ARRAY
			{
				return _symbols[offset + 1];
			}
			case 1: // $goal = $Types Types
			{
				return _symbols[offset + 2];
			}
			default:
				throw new IllegalArgumentException("unknown production #" + rule_num);
		}
	}
}
